package net.kem.utils.duplicatesfinder;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;


@SuppressWarnings("serial")
public class FileDuplicateCandidate implements DuplicateCandidate<Long, FileDuplicateCandidate> {
//	public static final boolean CALCULATE_DIGEST = true;
	private File _file;
	private String _fullName;
	private Long _size;
	private byte[] _digest;

	FileDuplicateCandidate(File file, Long size, boolean isCalculateDigest) {
		_file = file;
		_fullName = file.getAbsolutePath();
		_size = size;
		if(isCalculateDigest) {
			calculateDigest();
		}
	}

	private void calculateDigest() {
		InputStream is = null;
		try {
			MessageDigest digest = MessageDigest.getInstance("MD5");
			is = new FileInputStream(_fullName);
			int actuallyRead;
			byte[] buffer = new byte[1024 * 1024];
			while((actuallyRead = is.read(buffer)) != -1) {
				digest.update(buffer, 0, actuallyRead);
			}
			_digest = digest.digest();
		} catch (NoSuchAlgorithmException e) {
			_digest = new byte[0];
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			_digest = new byte[0];
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			_digest = new byte[0];
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if(is != null) {
				try {
					is.close();
				} catch (IOException e) {
					// Do nothing.
				}
			}
		}
	}

	public boolean isDuplicate(FileDuplicateCandidate another) {
		boolean res = MessageDigest.isEqual(getDigest(), another.getDigest());
		return res;
	}

	public boolean equals(Object obj) {
		if(this == obj) {
			return true;
		}
		if(obj instanceof FileDuplicateCandidate) {
			FileDuplicateCandidate fi = (FileDuplicateCandidate) obj;
			return _fullName.equals(fi._fullName);
		}
		return false;
	}

	public int hashCode() {
		return _size.hashCode();
	}


	public String toString() {
		return _size + "\tbytes hashed as " + _digest[0] + ',' + _digest[1] + ',' + _digest[2] + ',' + _digest[3] + " in " + _fullName;
	}

	public String getFullName() {
		return _fullName;
	}

	public Long getSize() {
		return _size;
	}

	public byte[] getDigest() {
		if(_digest == null) {
			calculateDigest();
		}
		return _digest;
	}

	public File getFile() {
		return _file;
	}
}